using System;
using System.Collections.Generic;
using System.Text;
using CMUSHrun.Events;
using System.Runtime.Serialization;
using System.Xml.Serialization;

/*
 * For info on serialization, see:
 *   http://msdn.microsoft.com/en-us/magazine/cc163902.aspx
 *   http://www.switchonthecode.com/tutorials/csharp-tutorial-serialize-objects-to-a-file
 *   http://www.4guysfromrolla.com/webtech/012302-1.shtml
 *   http://www.15seconds.com/issue/020903.htm
 */
namespace CMUSHrun.Objects
{
    /// <summary>
    /// The base mush object
    /// </summary>
    [Serializable,
    XmlRoot("GameObject")]
    public class MushObject : ISerializable
    {

        /// <summary>
        /// The object ID number
        /// </summary>
        protected Int32 _dbRef = -1;

        /// <summary>
        /// The object's name
        /// </summary>
        protected String _name = "";

        /// <summary>
        /// The list of items in this object
        /// </summary>
        protected List<MushObject> _inventory = new List<MushObject>();

        /// <summary>
        /// The object that is holding this object
        /// </summary>
        protected MushObject _container = null;

        protected Dictionary<String, MushAttribute> _attributes = new Dictionary<string, MushAttribute>();

        #region Public methods

        /// <summary>
        /// Constructor
        /// </summary>
        public MushObject()
        {        }

        /// <summary>
        /// The Database ID for this object
        /// </summary>
        public int DbRef
        {
            get
            {
                return _dbRef;
            }
            set
            {
                _dbRef = value;
            }
        }

        /// <summary>
        /// The object's name
        /// </summary>
        public String Name
        {
            get
            {
                return _name;
            }
            set
            {
                _name = value;
                MushAttribute ma = new MushAttribute();
                ma.Value = value;
                _attributes.Add("name", ma);
            }
        }

        /// <summary>
        /// The attributes on the object
        /// </summary>
        [System.Xml.Serialization.XmlIgnoreAttribute]
        public Dictionary<String, MushAttribute> Properties
        {
            get
            {
                return _attributes;
            }
        }

        /// <summary>
        /// The object that currently contains this object
        /// </summary>
        [System.Xml.Serialization.XmlIgnoreAttribute]
        public MushObject Container
        {
            get
            {
                return _container;
            }
            set
            {
                _container = value;
            }
        }

        /// <summary>
        /// Returns the inventory list for this object
        /// </summary>
        /// <returns>The inventory items in this item</returns>
        public List<MushObject> GetInventory()
        {
            return _inventory;
        }

        /// <summary>
        /// Consumes text published to this control
        /// </summary>
        /// <param name="source">The origin object providing the text</param>
        /// <param name="Text">The text provided</param>
        public void TextToObject(MushObject source, String Text)
        {
            OnTextToObject(source, Text);
        }

        /// <summary>
        /// Checks to see if the object is allowed to be removed from inventory
        /// </summary>
        /// <param name="subject">The object under question</param>
        /// <returns>True if the object is allowed to be removed</returns>
        public Boolean ObjectCanBeRemoved(MushObject subject)
        {
            return OnObjectCanBeRemoved(subject);
        }

        /// <summary>
        /// Checks if the Object is allowed to be added to this inventory
        /// </summary>
        /// <param name="subject">The object under question</param>
        /// <returns>True if the object is allowed to be removed</returns>
        public Boolean ObjectCanBeAdded(MushObject subject)
        {
            return OnObjectCanBeAdded(subject);
        }


        /// <summary>
        /// Adds the object to this inventory
        /// </summary>
        /// <param name="item">the item that is now at this location</param>
        public void AddToInventory(MushObject item)
        {
            _inventory.Add(item);

            // change the container
            item.Container = this;
        }


        /// <summary>
        /// Removes the object from the inventory
        /// </summary>
        /// <param name="item">the item to remove from the inventory</param>
        public void RemoveFromInventory(MushObject item)
        {
            _inventory.Remove(item);
        }

        #endregion

        #region Protected Overridable methods


        /// <summary>
        /// The custom test if an object is allowed to be removed from inventory
        /// </summary>
        /// <param name="subject">The object under question</param>
        /// <returns>True if the object is allowed to be removed</returns>
        protected virtual Boolean OnObjectCanBeRemoved(MushObject subject)
        {
            return true;
        }

        /// <summary>
        /// The custom test if an object is allowed to be added to the inventory
        /// </summary>
        /// <param name="subject">The object under question</param>
        /// <returns>True if the object is allowed to be removed</returns>
        protected virtual Boolean OnObjectCanBeAdded(MushObject subject)
        {
            return true;
        }

        /// <summary>
        /// Consumes text published to this control
        /// </summary>
        /// <param name="source">The origin object providing the text</param>
        /// <param name="Text">The text provided</param>
        protected virtual void OnTextToObject(MushObject source, String Text)
        {
            // No-op in the base class
            return;
        }

        #endregion

        #region ISerializable Members

        /// <summary>
        /// Constructor for deserialization
        /// </summary>
        /// <param name="info">the serialized parameters</param>
        /// <param name="context">the context</param>
        public MushObject(SerializationInfo info, StreamingContext context)
        {
            this._dbRef = info.GetInt32("_dbRef");
            this._name = info.GetString("name");
            //TODO figure out how to deserialize the container
            //this._container = 
            // info.AddValue("location", this._container);
        }

        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue("_dbRef", this._dbRef);
            if (this._container == null)
            {
                info.AddValue("location", -1);
            }
            else
            {
                info.AddValue("location", this._container.DbRef);
            }
            info.AddValue("name", this._name);
        }

        #endregion
    }

    
}
